package com.mathdroid.gui.main.character;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.util.HashMap;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.border.Border;

import com.mathdroid.gui.ImageLoader;
import com.mathdroid.gui.main.DroidFrame;
import com.mathdroid.gui.main.talents.TalentButton;
import com.mathdroid.model.EModelObserverEvent;
import com.mathdroid.model.IModelObserver;
import com.mathdroid.model.Model;
import com.mathdroid.model.enums.EItemSlot;
import com.mathdroid.model.enums.EItemType;
import com.mathdroid.model.enums.EModuleProficiency;
import com.mathdroid.model.items.Item;


/**
 * This frame can be used to edit the modules of an item.
 */
public final class ItemEnhancementFrame 
extends JFrame implements IModelObserver {

	/**
	 * Default UID.
	 */
	private static final long serialVersionUID = 1L;
	
	/**
	 * The slot of the item to enhance.
	 */
	private EItemSlot slot = null;
	
	/**
	 * The constraints for this UI components.
	 */
	private GridBagConstraints c = new GridBagConstraints();
	
	/**
	 * The space between components.
	 */
	private static final int SPACING = 10;
	
	/**
	 * The content of this frame.
	 */
	private JPanel p = new JPanel();
	
	/**
	 * The width and height of the buttons.
	 */
	private static final int BUTTON_EDGE = 50;
	
	/**
	 * The image loader.
	 */
	private final ImageLoader il = new ImageLoader();
	
	/**
	 * The item to edit.
	 */
	private Item item = null;
	
	/**
	 * The module buttons.
	 */
	private HashMap<EModuleProficiency, ItemButton> buttons = 
		new HashMap<EModuleProficiency, ItemButton>();
	
	/**
	 * Create a new item enhancement frame.
	 * @param s The slot of the "parent" item.
	 */
	public ItemEnhancementFrame(final EItemSlot s) {
		super();
		
		this.slot = s;
		this.item = Model.getProfile().getEquipedItems().get(this.slot);
		
		this.buildContentPanel();
		this.buildItemNameLabel();
		this.buildModuleSlots();
		
		this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
		this.setAlwaysOnTop(true);
		this.pack();
		
		this.addWindowListener(new ItemEnhancementWindowListener(this));
		
		DroidFrame f = Model.getDroidFrame();
		final int x = (int) (f.getLocation().getX() + f.getWidth() / 2 
				- this.getWidth() / 2);
		final int y = (int) (f.getLocation().getY() + f.getHeight() / 2 
				- this.getHeight() / 2);
		
		this.setLocation(x, y);
		
		this.setIconImage(new ImageIcon(
				TalentButton.class.getClass().getResource(
				"/com/mathdroid/gui/images/frameicon.png")).getImage());
		
		this.setVisible(true);
	}

	/**
	 * Add the module slots to the content panel.
	 */
	private void buildModuleSlots() {
		int i = 1;
		
		this.c.fill = GridBagConstraints.NONE;
		this.c.gridwidth = 1;
		this.c.gridy = 1;
		this.c.anchor = GridBagConstraints.WEST;
		
		for (EModuleProficiency mp : item.getModules().keySet()) {
			
			this.c.insets = new Insets(0, SPACING, SPACING, SPACING);
			this.c.gridy = i;
			this.c.gridx = 0;
			ItemButton b = new ItemButton(this.slot, mp, EItemType.MODULE);
			
			this.updateIcon(mp, b);
			
			b.setPreferredSize(new Dimension(BUTTON_EDGE, BUTTON_EDGE));
			this.buttons.put(mp, b);
			this.p.add(b, this.c);
			
			this.c.insets = new Insets(0, 0, SPACING, SPACING);
			this.c.gridx = 1;
			this.p.add(new JLabel(mp.toString()), this.c);
			i++;
		}
	}

	/**
	 * Update the icon of the button.
	 * @param mp The module slot that has to be updated.
	 * @param b The button that shows the module slot.
	 */
	private void updateIcon(final EModuleProficiency mp, final ItemButton b) {
		if (item.getModules().get(mp) != null) {
			String iconName = item.getModules().get(mp).getImageName();
			
			if (iconName != null) {
				b.setIcon(this.il.getItemIcon(iconName));
			} else {
				b.setIcon(this.il.getItemIcon("anonymous_module_50"));
			}
		} else {
			b.setIcon(this.il.getEmptyIcon50());
		}
	}

	/**
	 * Build the item name label.
	 */
	private void buildItemNameLabel() {
		this.c.insets = new Insets(SPACING, SPACING, SPACING, SPACING);
		this.c.anchor = GridBagConstraints.CENTER;
		this.c.gridwidth = 2;
		this.c.gridx = 0;
		this.c.gridy = 0;
		this.c.fill = GridBagConstraints.HORIZONTAL;
		this.c.weightx = 1;
		final JLabel lbl = new JLabel(item.getName());

		Border paddingBorder = 
			BorderFactory.createEmptyBorder(SPACING, SPACING, SPACING, SPACING);
		Border border = BorderFactory.createLineBorder(Color.GRAY, 2); 
		lbl.setBorder(
				BorderFactory.createCompoundBorder(border, paddingBorder));
		lbl.setHorizontalAlignment(SwingConstants.CENTER);
		this.p.add(lbl, this.c);
	}

	/**
	 * Build the content panel.
	 */
	private void buildContentPanel() {
		this.p.setLayout(new GridBagLayout());
		this.p.setBackground(Color.WHITE);
		this.add(this.p);
	}
	
	@Override
	public void modelChanged(final EModelObserverEvent e) {
		
		/*
		 * If a new profile is loaded or a new item template, there is no
		 * need for this frame.
		 */
		if (e == EModelObserverEvent.PROFILE_LOADED 
				|| e == EModelObserverEvent.EQUIPPED_ITEMS_LOADED) {
			Model.unregisterObserver(this);
			this.dispose();
		}
		
		if (e == EModelObserverEvent.EQUIPPED_ITEMS_CHANGED) {
			this.refresh();
		}
	}

	/**
	 * Refresh the icons of this item slot.
	 */
	private void refresh() {
		Item i = Model.getProfile().getEquipedItems().get(this.slot);
		ItemButton b = null;

		if (i != null) {
			for (EModuleProficiency mp : i.getModules().keySet()) {
				b = this.buttons.get(mp);
				this.updateIcon(mp, b);
			}
		}
	}

}
